Из чего состоит типичная форум-система
Создание и подготовка базы данных
Просмотр списка сообщений в режиме администрирования (файл Admin-List.asp)
Редактор сообщения (файл Edit-Del.asp)
Отправка сообщения (файл Post.asp)
В предыдущей статье серии «<% ASP на блюдечке %>» мы рассмотрели процесс создания такого важного компонента современного Интернета, как форум и конференция. Как и было обещано, предметом настоящей статьи станут инструменты контроля и администрирования форум-системы, то есть все то, что лежало в рассмотренной нами главной страничке под ссылкой: «Для администрирования системы жми сюда» (см. рис. 1). Попросту говоря, в данной статье рассматривается процесс создания Web-основанной системы управления форумом. И хотя в общем случае решить эту задачу возможно и с привлечением других средств (например, написанием программы на C++), тем не менее именно Web-интерфейс в данном случае остается наиболее удобным решением. Однако не будем забегать вперед, а для лучшего представления задачи повторим основы создания форума.
Для начала давайте вспомним концепцию простейшей форум-системы с точки зрения потенциального клиента, что позволит нам в дальнейшем очертить задачу построения форума и для программиста. В данном случае нам прежде всего необходимо обратить внимание на вопросы управления форумами и задуматься над возможностями автоматизации этих процессов. Предположим, мы уже знаем, что такое форум, более того, можем сами создавать форум-систему (нам это известно из предыдущей статьи). Давайте еще раз попытаемся упорядочить свои собственные представления о форуме. Обратим особое внимание прежде всего на функции администрирования форум-систем.
Итак, во-первых, как нам известно, форум — это некая область экрана (окна браузера), где различные его участники (будем называть их пользователями форум-системы или просто пользователями) могут излагать свои мысли на заданную тему, придавая им форму текстовых сообщений. Просматривая сообщения, каждый пользователь волен написать сообщение в ответ на чье-либо уже написанное сообщение, которое, в свою очередь, тоже может являться ответом на сообщение и т.д.
Обобщая, можно сказать, что форум представляет собой двухмерный поток текстовых сообщений. Под вторым измерением следует понимать сообщения-ответы, ответы на ответы и т.д.
Не правда ли, для нас с вами концепция форума стала гораздо понятнее и доступнее? Теперь можно переходить к рассмотрению и некоторых отличительных особенностей форумов. Конечно, это не догма, и не все форумы обладают такими особенностями, однако все они (эти особенности), как правило, присутствуют в современных форум-системах.
Во-первых, это система идентификации пользователей, призванная регистрировать имя (псевдоним, nickname), пароль, электронный адрес и т.д. пользователя для обеспечения его уникальности в форум-системе.
Во-вторых, это, как правило, система управления форумом, позволяющая осуществлять контроль за потоком текстовых сообщений. В современных системах данная функция возложена на так называемых модераторов или форум-менеджеров.
Что же следует понимать под форум-управлением?
Вкратце список функций управления форумами можно представить следующим образом:
Список можно и продолжить, но, на наш взгляд, именно без вышеперечисленного не обходится ни одна форум-система.
Во-вторых, как следует из вышеприведенного списка, это система безопасности, обеспечивающая модераторов и администраторов форума доступ к функциям, недоступным для других пользователей.
В-третьих, это система поиска сообщений и (или) их авторов как по тематике, так и по содержимому сообщения.
Конечно, существуют варианты с выбором картинки-смайлика и цвета текстового сообщения, но сути задачи это не меняет.
Совокупность вышеуказанных трех компонентов и является, по существу, самым обычным и зачастую самым распространенным Интернет-форумом.
Как вероятно читатель уже догадался, в разрабатываемой нами системе мы будем отличать контроль и поддержку форумов от организации общего управления ими в первую очередь по ролям. Контроль и поддержка (первые три функции управления) будут относиться к обязанностям модератора каждого конкретного форума, а общее управление (назначение модераторов, создание, редактирование и удаление форумов) — к обязанностям администратора форум-системы. Отсюда следствие: у форум-системы может быть много модераторов, но лишь один администратор.
Теперь, когда мы уяснили, что представляет собой форум-система с точки зрения пользователя, можно переходить и к постановке и формализации программной задачи.
Итак, необходимо разработать:
В предыдущей статье серии мы разработали первые три пункта поставленной нами задачи, а теперь настала пора разобраться и с четвертым (последним) пунктом.
Предполагается, что читатель знаком с основами ASP- и SQL-программирования (первых частей настоящей статьи для этого будет вполне достаточно). Кроме того, нам потребуется Microsoft Access 97 или 2000, какой-нибудь HTML или текстовый редактор (рекомендую использовать Macromedia Dreamweaver UltraDev 4.0) и немного терпения.
Создадим три таблицы: таблицу пользователей (ForumUsers), таблицу форумов (ForumsTable) и таблицу текстовых сообщений (MessagesTable). Представим себе их взаимосвязь следующим образом: Файл Images\DB.gif
Таблица ForumUsers будет служить для хранения имен и паролей администраторов системы, и ее редактирование не будет доступно непосредственно с помощью Web-интерфейса.
Таблица ForumsTable будет хранить информацию о доступных форумах, их именах и паролях доступа их модераторов и может редактироваться непосредственно с помощью Web-интерфейса в режиме администрирования.
Таблица MessagesTable будет содержать весь поток всех сообщений участников всех форумов и, разумеется, тоже будет пополняться с помощью Web-интерфейса в обычном режиме и редактироваться с помощью Web-интерфейса в режиме администрирования.
Теперь, когда база данных готова, можно приступать к созданию и самой системы администрирования форума.
Универсальный набор функций (файл common-admin.asp)
Прежде чем приступить к разработке самой системы управления форумом, вынесем все типовые функции, которые нам понадобятся многократно, в один файл, который по мере необходимости будем впоследствии «включать» в разрабатываемые странички. Давайте разберемся, что же нам понадобится?
Во-первых, это заголовок и «концевик» HTML-файлов наших ASP-страниц (их придется создавать достаточно часто); во-вторых, это функции соединения и закрытия соединения с базой данных; в-третьих, функция, упорядочивающая дочерние сообщения (сообщения ответы на сообщения), функция посылки уведомления пользователям по электронной почте, функция выбора последнего введенного значения, функция изменения цвета для раскраски строк таблиц и функция контроля уровня доступа:
<%
option explicit
response.buffer=true
response.write "<meta charset='visual'>"
dim line
line = "<img src='images/line.gif' width=600 height=1><br><br>"
Sub Header()
Response.Write "<head><meta http-equiv='Content-Type' content='text/html; charset=windows-1251'>"
Response.Write "<TITLE>ASP Форум (Администрирование)</TITLE>"
Response.Write "</HEAD><body>"
Response.Write "<table border=0 cellpadding=0 cellspacing=0>"
End Sub
Sub admin()
Response.Write "<br><br><A HREF='administration/main.asp'>-----------</a>"
End Sub
Response.Buffer = true
dim dsn,conn,rs,sql
dsn = "DBQ=" & Server.Mappath("../Data/Forum.mdb") & ";Driver={Microsoft Access Driver (*.mdb)};"
Sub Connect()
set conn = server.createobject("adodb.connection")
set rs = server.createobject("adodb.recordset")
conn.open dsn
End Sub
Sub Close()
rs.close
set rs = nothing
conn.close
set conn = nothing
End Sub
Sub Footer()
Response.Write "<tr><td><br>"
Response.Write "<img src='images/line.gif' width=600 height=1><br><br>"
Response.Write "</body></html>"
End Sub
Sub displayMessages(layer,id)
dim sql_order,rs_order,image,str,MessageSpacing,mesid,spaceing,tid
set rs_order=server.createObject("adodb.recordset")
sql_order = "SELECT * FROM MessagesTable WHERE thread_parent = " & id & "and thread_parent <> 0"
rs_order.open sql_order,conn
Do Until rs_order.eof
mesid = rs_order("id")
name = rs_order("name")
email = rs_order("email")
subject = rs_order("subject")
mesdate = rs_order("mesdate")
fid = rs_order("forumID")
tid = rs_order("thread_id")
image="<img src='../images/arr1.gif' border=0>"
str=""
spaceing=""
For MessageSpacing = 1 To layer
spaceing = spaceing & " "
Next
str = "<tr><td>"
str = str & spaceing & image & "<a href='../show.asp?id=" & mesid &_
"&fid="&fid&"&tid="&tid&"'>" & subject & "</a>" & "...." & mesdate
str = str & "...." & name & " <a href='edit-del.asp?action=edit&id=" & mesID &_
"&fid="&fid&"&tid="&tid&"'>(Редактировать </a>" &_
"<a href='edit-del.asp?action=del&id=" & mesid &_
"&fid="&fid&"&tid="&tid&"'> | Удалить) </a>"
str = str & "</tr></td>"
str = str & "</b>"
Response.Write str
Call displayMessages(layer+1,mesid)
rs_order.MoveNext
Loop
rs_order.close
set rs_order = nothing
End Sub
Sub sendAllFamily(tid,maxid,fid)
dim body,email,link,rs_send
set rs_send=server.createObject("adodb.recordset")
sql="select email,id,thread_id from MessagesTable"
sql=sql & " where (thread_id="& tid & " or id="& tid & ") and id<>" & maxid &""
sql=sql & "and forumid="&fid&" and isChecked=1"
rs_send.open sql,conn
Do While Not rs_send.eof
link="http://localhost/show.asp?fid=" & fid & "&id=" & maxid & "&tid=" & tid
email=rs_send("email")
response.write email
Body = "Поступило новое сообщение на форум"
Body = Body & "Адрес поступившего сообщения: "
Body = Body & link
Dim objCDO
Set objCDO = Server.CreateObject("CDONTS.NewMail")
objCDO.To = email
objCDO.From = "rouben@iname.com"
objCDO.Subject = "Уведомление о поступлении сообщения!"
objCDO.Body = body
objCDO.Send
rs_send.MoveNext
Loop
rs_send.close
set rs_send = nothing
End Sub
Sub maxRec()
set rs_maxid=server.createobject("adodb.recordset")
sql_maxid = "select max(id) as maxid from MessagesTable"
Set rs_maxid = Conn.Execute(sql_maxid)
maxid = rs_maxid("maxid")'new id
rs_maxid.close
set rs_maxid=nothing
End Sub
Function changeColor()
If flag = 0 Then
flag = 1
color = "LightBlue"
Else
flag = 0
color = "White"
End if
End Function
Sub secure_general()
If session("status") <> "admin" Then
Response.Redirect "error.htm"
End If
End Sub
%>
Остановимся на извлечении идентификатора последнего введенного значения и на функции посылки уведомлений о поступлении нового сообщения по электронной почте. Первая функция попросту извлекает максимальное значение идентификатора сообщения. А так как идентификаторы (identity) таблиц баз данных уникальны и постоянно инкрементируются, то фактически эта функция возвращает идентификатор последнего сообщения. В случае если это действие выполняется непосредственно после добавления в таблицу, а в данном случае это именно так, то извлекаемое значение совпадает с идентификатором последнего введенного значения, то есть последнего сообщения.
По сути, функция посылки уведомительных сообщений о поступлении новых сообщений в цикле по результатам запроса сообщений, авторы которых пожелали получать уведомление по электронной почте, посылает сообщения, используя серверный объект CDONTS. Выборка этих сообщений из таблицы сообщений выглядит следующим образом:
sql = "select email,id,thread_id from MessagesTable" sql = sql & " where (thread_id="& tid & " or id="& tid & ") and id<>" & maxid &"" sql = sql & "and forumid="&fid&" and isChecked=1"
где флажок isChecked и отражает предпочтение пользователя о посылке уведомления по электронной почте.
Почти все функции и процедуры нам знакомы, за исключением, пожалуй, двух последних. Функция changeColor() позволяет изменять атрибут цвета в зависимости от состояния флажка flag и применяется для раскраски строк таблиц. Процедура secure_general() используется для обеспечения безопасности форум-системы и служит для перенаправления пользователей на страницу с текстом о невозможности доступа к режиму администрирования в случае, если значение сессионной переменной session("status") не равно константе "admin".
Главная страничка — выбор режима администрирования (файл index.asp)
Теперь необходимо создать страничку, в которой пользователь сможет выбрать себе роль администратора или модератора. Для этого необходимы две формы с запросом имени и пароля, контролирующие корректность ввода последних и допускающие вход в систему управления с соответствующими функциями и правами:
<!--#include file="common-admin.asp"-->
<%
dim useraction,username,password,forumid
useraction=request("action")
Select Case userAction
Case "login"
username = Trim (request.form("username"))
password = Trim (request.form("password"))
Call Connect()
sql="select username,password from ForumUsers where username='"&username&_
"' and password='"&password&"'"
rs.open sql,conn
If rs.eof AND rs.bof Then
Response.Write "<b>Проверьте правильность ввода имени и (или) пароля</b><br><br>"
Else
Session("status") = "admin"
Response.Redirect "main.asp"
End If
Call Close()
Case "f_login"
username=trim(request.form("username"))
password=trim(request.form("password"))
Call Connect()
sql="select forumid,username,password from ForumsTable where username='"&username&"' and password='"&password&"'"
rs.open sql,conn
If rs.eof AND rs.bof Then
response.write "<b>Проверьте правильность ввода имени и (или) пароля</b><br><br>"
Else
forumid = rs("forumid")
Session ("status") = forumid
Response.Redirect "admin-list.asp?fid="&forumid
End If
Call Close()
End Select
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>ASP - Форум своими силами (Администрирование)</title>
</head>
<body>
<table border=1 bgcolor = "#FFCC99">
<form action="index.asp?action=login" method="post">
<tr>
<td colspan=2 align = center>Администратор форума</td>
</tr>
<tr align=right><td>Имя:</td>
<td><input type="text" name="username" size=15 maxlength=10></td>
</tr>
<tr align=right>
<td>Пароль:</td>
<td><input type="password" name="password" size=15 maxlength=10></td>
</tr>
<tr>
<td colspan=2 align=center><input type="submit" name="submit" value="Вход"></td>
</tr>
</form>
</table>
<br><br>
<table border=1 bgcolor = "#FFCC99">
<form action="index.asp?action=f_login" method="post">
<tr>
<td colspan=2 align=center>Модератор форума</tr></td>
<tr align=right>
<td>Имя:</td>
<td><input type="text" name="username" size=15 maxlength=10></td>
</tr>
<tr align=right>
<td>Пароль:</td>
<td><input type="password" name="password" size=15 maxlength=10></td>
</tr>
<tr>
<td colspan=2 align=center><input type="submit" name="submit" value="Вход">
</td>
</tr>
</form>
</table>
<br><a href="javascript:history.back(-1)">Назад</a> | <a href="../index.asp">Главная страница</a>
</body>
</html>
Форум-редактор в режиме администрирования (файл main.asp)
Теперь нам будет необходима страничка просмотра всех форумов, а также прикрепленных к ним модераторов, их учетных записей и паролей, причем с возможностью как создания и редактирования форумов, так и их удаления:
<!--#include file="common-admin.asp"-->
<%
Call secure_general()
dim useraction
dim username, password, topic, secure
dim id, flag, color
userAction = request("action")
Select Case userAction
Case "add"
username = request.form("username")
password = request.form("password")
topic = request.form("topic")
secure = 0
Call Connect()
sql="select forumname,username,password from ForumsTable where forumname='" & topic &_
"' or password='"&password&"'"
rs.open sql,conn
If rs.eof AND rs.bof Then
conn.execute("insert into ForumsTable (forumname, username, password, isSecure) " &_
"values('"&topic&"','"&username&"','"&password&"','"&secure&"')")
Else
response.write "<script>alert('Повтор названия форума или пароля недопустим!')</script>"
End If
Call Close()
End Select
Call Connect()
sql="select * from ForumsTable order by forumid"
rs.open sql,conn
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>ASP - Форум своими силами – Форум-редактор</title>
<script>
function IsDel()
{
if (confirm("Вы уверены, что хотите удалить этот форум?")) {
return true;
}
else {
return false;
}
}
</script>
</head>
<body>
<table border=1 cellspacing=2>
<tr>
<td><b>Название форума</b></td>
<td><b>Имя</b></td>
<td><b>Пароль</b></td>
<td><b>Редактировать</b></td>
<td><b>Удалить</b></td>
</tr>
<%
Do while not rs.eof
changeColor()
id = rs("forumid")
Response.Write "<tr bgcolor="& color &"><td>"
Response.Write rs("forumname") & "</td><td>"
Response.Write rs("username") & "</td><td>"
Response.Write rs("password") & "</td><td>"
Response.Write "<a href='editdel.asp?id="&id&"&action=edit'>Редактировать</td><td><a href='editdel.asp?id="&id&"&action=del'onclick='return IsDel()'>Удалить</td></tr>"
rs.MoveNext
Loop
Call Close()
Response.Write "</table><br></table>"
%>
<table border=2 width=380>
<tr>
<td colspan=2>Добавление нового форума.
<br> Введите название форума, а также имя и пароль его модератора
</td>
</tr>
<form action="main.asp?action=add" method="post">
<tr align=left>
<td>Имя:</td>
<td><input type="text" name="username" size="35" maxlength="10"></td>
</tr>
<tr align=left>
<td>Пароль:</td>
<td><input type="password" name="password" size="35" maxlength="10"></td>
</tr>
<tr align=left>
<td>Название:</td>
<td><input type="text" name="topic" size="35" maxlength="50"></td>
</tr>
<tr align=left>
<td colspan=2 align=center>
<input type="submit" name="submit" value="Добавить форум">
<input type="Reset" value="Сброс">
</td>
</tr>
</form>
</table>
<p><a href="javascript:history.back(-1)">Назад</a> | <a href="../index.asp">Главная страница</a></p>
</body>
</html>
Как видите, все просто, и результатом формирования странички, по сути, будет таблица с форумами, в каждой строке которой будут отображены сведения об одном из форумов и будут присутствовать ссылки на функции редактирования атрибутов форума и его удаления из форум-системы. Далее будет следовать форма добавления новых форумов в форум-систему (см. рис. 2).
Особое внимание следует обратить на то, каким образом идентифицируются модераторы в нашей форум-системе. Дело в том, что для соблюдения однозначности мы будем запрещать повторение паролей модераторов, и кроме того, необходимо также обеспечить уникальность и в названиях форумов. Следующий код как раз и призван для этого:
… sql="select forumname, username, password from ForumsTable where forumname='" & topic &_ "' or password='"&password&"'" rs.open sql,conn …
…
If rs.eof AND rs.bof Then
conn.execute("insert into ForumsTable (forumname, username, password, isSecure) " &_
"values('"&topic&"','"&username&"','"&password&"','"&secure&"')")
Else
response.write "<script>alert('Повтор названия форума или пароля недопустим!')</script>"
End If
…
Редактирование атрибутов форума (файл EditDel.asp)
Эта страничка загружается в том случае, если перейти по ссылке редактирования форума в режиме администрирования, и позволяет редактировать название форума, имя его модератора, а также пароль подступа к привилегированному режиму, в котором модератор сможет редактировать сообщения других пользователей (участников) обсуждения, а также удалять нежелательные сообщения из их потока:
<!--#include file="common-admin.asp"-->
<%
Call secure_general()
Response.CacheControl = "no-cache"
Response.AddHeader "Pragma", "no-cache"
Response.Expires = -1
dim useraction
dim id, sql_c, sOne, sZero, secure
dim username,password,forumname
id=request("id")
userAction = request("action")
call connect()
Select Case userAction
Case "update"
id = request.form("id")
username = request.form("username")
password = request.form("password")
forumname = request.form("topic")
secure = 0
sql_c="select forumname, username, password, issecure from ForumsTable where" &_
" ( forumname='"&forumname&"' or password='"& password & "' ) and forumid<>"&id&""
set rs = conn.execute(sql_c)
If rs.eof AND rs.bof Then
sql = "update ForumsTable SET "&_
forumname='" & forumname & "', username='" & username & "', password='" & password &_
"', isSecure=" & secure & " where forumid="&id
conn.execute(sql)
response.redirect "main.asp"
Else
response.write "<script>alert('Введите другое имя /пароль');location.href='main.asp';</script>"
End If
conn.close
set conn = nothing
Case "del"
sql = "delete from ForumsTable where forumid="&id
conn.execute(sql)
conn.close
set conn = nothing
response.redirect "main.asp"
Case "edit"
sql = "select * from ForumsTable where forumid="&id
set rs = conn.execute(sql)
username=rs("username")
password=rs("password")
forumname=rs("forumname")
secure = rs("issecure")
if secure="0" then
sOne=""
sZero="checked"
Else
sOne="checked"
sZero=""
End If
End Select
conn.close
set conn = nothing
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>ASP Форум (Редактирование атрибутов форума)</title>
</head>
<body>
<a>Редактирование атрибутов форума</a><br><br>
<table border=2 width=400 align=left>
<tr align = left>
<td colspan = 2>Введите название форума и имя модератора, а также пароль</td>
</tr>
<form action="editdel.asp?action=update" method="post">
<input type=hidden name=id value='<%=id%>'>
<tr align=left>
<td>Имя:</td>
<td><input type="text" name="username" size="25" value='<%=password%>' maxlength="10"></td>
</tr>
<tr align=left>
<td>Пароль:</td>
<td><input type="text" name="password" size="25" value='<%=password%>' maxlength="10"></td>
</tr>
<tr align=left>
<td>Название форума:</td>
<td><input type="text" name="topic" size="25" maxlength="50" value='<%=forumname%>'></td>
</tr>
<tr align=left>
<td colspan=2 align=center><input type="submit" name="submit" value="Обновление данных"> <input type="Reset" value="Сброс"></td>
</tr>
</form>
</table>
<br><br><br><br><br><br><br><br><br><br><br><br>
<p><a href="javascript:history.back(-1)">Назад</a> | <a href="../index.asp">Главная страница</a></p>
</body>
</html> Нам потребуется страничка просмотра списка сообщений, извлекающая сообщения выбранного пользователем форума из таблицы всех сообщений и
организующая показ сообщений иерархически, то есть сдвигая сообщения-ответы вправо, сообщения-ответы на ответы еще правее и т.д.
<!--#include file="common-admin.asp"-->
<%
dim fid,tp,tid
dim rs_fn
dim ParentID,name,email,subject,mes,mesdate,image
dim forumname
Function getForumName(id)
set rs_fn=server.createObject("adodb.recordset")
sql="select forumid,forumname from ForumsTable where forumid="&id
rs_fn.open sql,conn
forumname = rs_fn("forumname")
response.write "<tr><td><b>" & forumname & "<br><br></b></TR></TD>"
rs_fn.close
set rs_fn=nothing
End Function
'Извлечем идентификатор текущего форума
fid = request("fid")
If CInt (session("status")) <> CInt(fid) OR session("status") = "" Then
Response.Redirect "error.htm"
End If
image = "<img src='../images/arr.gif' border=0>"
Call Header()
%>
<script>
function IsDel()
{
if (confirm("Вы уверены, что хотите удалить это сообщение?")) {
return true;
}
else {
return false;
}
}
</script>
<%
sql="select id, thread_id, name, email, subject, mesdate, forumID, thread_parent from MessagesTable "&_
"WHERE (forumid = " & fid & ") and thread_parent=0 order by id desc"
call connect()
rs.open sql,conn
If rs.eof and rs.bof then ' Если сообщений нет
Response.Write "<tr><td>Сообщений нет</tr></td>"
Else ' Показ всех сообщений
Response.Write getForumName(fid)
Do While Not rs.eof
tid = rs("thread_id")
ParentID=rs("id")
name=rs("name")
email=rs("email")
subject=rs("subject")
mesdate=rs("mesdate")
Response.write "<tr><td>"
Response.write image & "<a href='../show.asp?id=" & parentID & _
"&fid="&fid&"&tid="&tid&"'>" & subject & "</a>" & "...." & mesdate & "...." & name & "</a>"
Response.write " <a href='edit-del.asp?action=edit&id=" & parentID & _
"&fid="&fid&"&tid="&tid&"'>(Редактировать </a>" & _
"<a href='edit-del.asp?action=del&id=" & parentID & _
"&fid="&fid&"&tid="&tid&"' onclick='return IsDel()'> | Удалить) </a></tr></td>"
'Покажем дочерние сообщения
Call displayMessages(1,ParentID)
rs.MoveNext
Loop
End If
Call Close()
Response.Write "<tr><td><br>"
Response.Write "<br><br><a href='post.asp?fid=" & fid & "'>Послать сообщение как модератор форума</a>"
Response.Write "</table><br>"
%>
<p><a href="javascript:history.back(-1)">Назад</a> | <a href="../index.asp">Главная страница</a></p>
</body>
</html>
Согласитесь, все довольно просто. Результатом формирования странички списка является набор ссылок на странички просмотра отдельных сообщений (на страничку show.asp, которой в качестве параметра передается строка с идентификатором сообщения), и уровня вложенности: show.asp?id=" & parentID & "&fid="& fid &"&tid=" & tid", то есть точно таким же образом, как мы это описывали в предыдущей части статьи.
Самое главное в этой страничке заключается в выводе дочерних сообщений. Осуществляется это посредством вызова функции displayMessages.
Данная функция осуществляет вывод всех дочерних сообщений, причем в качестве параметров этой функции передаются уровень, с которого необходимо начать вывод дочерний сообщений, а также идентификатор сообщения-родителя.
Теперь нам (а точнее, нашим модераторам) будет нужен довольно простой редактор сообщений, позволяющий редактировать заголовок сообщения, атрибуты его автора, а также сам текст сообщения:
<%
option explicit
dim fid
dim useraction
dim dsn,sql,conn,rs
dim name,subject,email,id,mesBody
id = request("id")
fid = request("fid")
If CInt(session("status")) <> cint(fid) OR session("status") = "" Then
Response.Redirect "error.htm"
End If
userAction = request("action")
dsn = "DBQ=" & Server.Mappath("../Data/Forum.mdb") & ";Driver={Microsoft Access Driver (*.mdb)};"
'dsn = "Forum"
set conn = server.createObject("adodb.connection")
conn.open dsn
Select Case userAction
Case "update"
id=request.form("id")
name=request.form("name")
subject=request.form("subject")
email=request.form("email")
mesBody = request.form("mesBody")
mesbody = Replace(mesbody, vbCrLf, "<br>")
sql = "update MessagesTable SET mesBody = '"&mesBody &_
"', subject='" & subject&"', name = '" & name &_
"', email = '" & email & "' where id="&id
conn.execute(sql)
conn.close
set conn = nothing
response.redirect "admin-list.asp?fid=" & fid
Case "del"
id = request.querystring("id")
sql = "delete from MessagesTable where id="&id
conn.execute(sql)
conn.close
set conn = nothing
response.redirect "admin-list.asp?fid=" & fid
Case "edit"
sql = "select * from MessagesTable where id="&id
set rs = conn.execute(sql)
name=rs("name")
subject=rs("subject")
email=rs("email")
mesBody=rs("mesBody")
mesbody = Replace(mesbody, "<br>",vbCrLf)
conn.close
set conn = nothing
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>ASP Форум (Редактирование сообщения)</title>
</head>
<body>
<table border=1 width=400>
<tr>
<td colspan=2><b>Редактирование сообщения</b><br></td>
</tr>
<form action="edit-del.asp?action=update" method="post">
<input type=hidden name=id value=<%=id%>>
<input type=hidden name=fid value=<%=fid%>
<tr>
<td>Имя:</td>
<td><input type="text" name="name" size=20 maxlength=20 value='<%= name %>'>
</td>
</tr>
<tr>
<td>Tema:</td>
<td><input type="text" name="subject" size=20 maxlength=20 value='<%= subject %>'>
</td>
</tr>
<tr>
<td>E-mail:</td>
<td><input type="text" name="email" size=20 maxlength=20 value='<%= email %>'>
</td>
</tr>
<tr>
<td>Сообщение:</td>
<td><textarea cols=25 rows=8 name='mesBody' maxlength='20' size=23 wrap="virtual" ><%=mesBody%></textarea>
</td>
</tr>
<tr>
<td colspan=2 align="center">
<input type="submit" value="Update">
</td>
</tr>
</form>
</table>
</body>
</html>
<% End Select %> На этом этапе нам надлежит сформировать формы посылки сообщения от имени модератора. Единственным отличием от обычной формы посылки сообщения здесь является то, что вместо имени пользователя в соответствующее поле формы отправки по умолчанию будет загружено значение «Модератор». Далее, как и в обычном случае, нам потребуется реализовать проверку корректности заполнения формы, обработку введенных значений и механизм добавления новых сообщений в соответствующую таблицу базы данных.
Извлечем идентификатор текущего форума, сообщения и его уровня вложенности, а затем опросим действия пользователя. Данные, введенные пользователем в качестве тела сообщения, а также его заголовка (темы) и имени пользователя, обработаем с использованием серверного метода Server.HtmlEncode: mesbody = Server.HtmlEncode(mesbody), после чего можем добавлять новую запись в таблицу:
<!--#include file="common-admin.asp"-->
<SCRIPT LANGUAGE=VBScript RUNAT=Server>
<!--Metadata type="typelib" File="c:\program files\common files\system\ado\msado15.dll" -->
</SCRIPT>
<%
dim useraction,fid,action,id,tid,mailme
dim mesbody,name,subject
dim sql_maxid,rs_maxid,maxid
fid = request("fid")
id = request("id")
tid = request("tid")
If CInt(session("status")) <> CInt(fid) OR session("status")="" Then
Response.Redirect "error.htm"
End If
If id="" Then
action="post.asp?action=save"
Else
action="post.asp?action=replay"
End If
userAction = request("action")
Select Case userAction
Case "save"
call connect()
sql="select * from MessagesTable"
RS.Open sql, Conn, 3, adLockOptimistic
mesbody=request.form("message")
name=request.form("name")
name = "**" & name & "**"
subject=request.form("subject")
mailme=request.form("mailme")
rs.addnew
rs("name")=name
rs("subject")=subject
rs("email")=request.form("email")
rs("mesdate")=now()
rs("mesbody")=mesbody
rs("thread_parent")=0
rs("thread_id")=0
rs("forumID")=request.form("fid")
rs("isChecked")=mailme
rs.update
call close()
response.redirect "../list.asp?fid="&fid
End Select
dim requireFldSign
requireFldSign = "<font color='red'>*</font>"
response.write "<HTML><HEAD><link rel='stylesheet' href='style.css'>"
%>
<script language="javascript">
function submitit()
{
var name = document.myform.name.value;
var subject = document.myform.subject.value;
var email = document.myform.email.value;
if (name == "") {
alert("Введите Ваше имя.")
document.myform.name.focus()
return false
}
if (subject == "") {
alert("Введите тему")
document.myform.subject.focus()
return false
}
if (email!="") {
if (email.indexOf('@', 0) == -1 || email.indexOf('.', 0) == -1) {
alert("Некорректный формат электронного адреса");
document.myform.email.focus()
return false
}
}
}
</script>
<%
response.write "<meta http-equiv='Content-Type' content='text/html; charset=windows-1251'>"
response.write "<TITLE></TITLE></HEAD><body>"
response.write "<b>Послать сообщение как модератор форума</b><br><br>"
response.write "<table border=0 width=600 cellpadding=0 cellspacing=0>"
response.write "<tr><td width=100></tr></td>"
response.write "<form name='myform' action='" &action & "' method='post' onsubmit='return submitit()'>"
response.write "<input type=hidden name='fid' value='"&fid&"'>"
response.write "<input type=hidden name='id' value='"&id&"'>"
response.write "<input type=hidden name='tid' value='"&tid&"'>"
response.write "<tr><td width=100>"
response.write requireFldSign & "Имя:</td><td><input type='text' name='name' maxlength='20' size=23 value='Модератор'></tr></td>"
response.write "<tr><td>"
response.write "E-mail:</td><td><input type='text' name='email' maxlength='28' size=23></tr></td>"
response.write "<tr><td>"
response.write requireFldSign & "Тема:</td><td><input type='text' name='subject' maxlength='25' size=23></tr></td>"
response.write "<tr><td valign=top>"
response.write "Сообщение:</td><td><textarea cols=25 rows=8 name='message' maxlength='20' size=23 wrap='virtual'></textarea></tr></td>"
response.write "<tr><td colspan=2><br>"
response.write "<input type='checkbox' name='mailme' value='1'>"
response.write "Отправить электронное уведомление об ответах</tr></td>"
response.write "<tr><td colspan=2><br>"
response.write "<input type='submit' name='submit' value='Отправить сообщение'> "
response.write "<input type='reset' name='reset' value='Сброс'>"
response.write "</form>"
response.write "</tr></td></table></body></html>"
response.write "<table border=0 width=600 cellpadding=0 cellspacing=0><tr><td>"
Call Footer()
Response.Write "</tr></td></table>"
%>
По своей сути эта страничка очень похожа на аналогичную страничку посылки сообщения, рассмотренную нами выше.
Наконец, нам осталось разместить все исходники наших страниц в папке с именем Administration, и тогда наша форум-система будет окончательно готова к использованию.
Полный архив исходных текстов ASP-страниц к настоящей и предыдущей частям статьи лежит здесь.
КомпьютерПресс 6'2001